<template>
  <div @mouseup="clearEvent" @mouseleave="clearEvent" style="padding: 25px;">
    <div class="slider" ref="sliderRef">
      <Tooltip :title="current + ''">
        <div class="slider-ball" @mousedown="clickBlock" :style="{ left: left + 'px' }" ref="sliderBallRef"></div>
      </Tooltip>
      <div class="slider-block" @mousedown="clickBlock" ref="sliderBlockRef"></div>
      <div class="slider-block-active"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, defineProps, ref, defineEmits, watch } from 'vue'
import Tooltip from '@/components/Tooltip/tooltip.vue'

type SliderPropsType = {
  default?: number | undefined
  range: [number, number]
  disabled?: boolean | undefined
}

const props = defineProps<SliderPropsType>()

const sliderBlockRef = ref<null | HTMLDivElement>(null)
const sliderRef = ref<null | HTMLDivElement>(null)
const sliderBallRef = ref<null | HTMLDivElement>(null)
const left = ref<number>(0)
const current = ref<number>(0)

const emit = defineEmits(['change'])

// 根据range对进度条进行分组
const blockGroupByRange = computed(() => {
  const [start, end] = props.range
  const size = end - start

  // 将整个滑块平分
  const { width } = sliderBlockRef.value!.getBoundingClientRect()

  const groupSize = width / size
  return {
    groupSize,
    groupNum: size,
    width
  }
})

// 获取球的宽度
const BallWidth = computed(() => {
  const { width } = sliderBallRef.value!.getBoundingClientRect()
  return width
})

// 获取鼠标当前位置
const getCurrentLocation = (e: MouseEvent) => {
  let location = 0
  const { offsetX } = e
  let moveBlockNum = 0

  if (e.target === sliderBallRef.value) {
    moveBlockNum = Math.round((offsetX + left.value) / blockGroupByRange.value.groupSize)
    const moveLocation = moveBlockNum * blockGroupByRange.value.groupSize
    location = moveLocation - BallWidth.value / 2
  } else {
    moveBlockNum = Math.round(offsetX / blockGroupByRange.value.groupSize)
    const moveLocation = moveBlockNum * blockGroupByRange.value.groupSize
    location = moveLocation - BallWidth.value / 2
  }

  if (location < 0) {
    location = 0
  }

  if (location > blockGroupByRange.value.width) {
    location = blockGroupByRange.value.width
  }
  const [start] = props.range
  const currentLocation = moveBlockNum + start

  if (currentLocation !== current.value) {
    current.value = currentLocation
    emit('change', currentLocation)
  }
  left.value = location
}

// 滑块移动到指定位置
const scrollByCurrentRange = (value: number | undefined) => {
  if (!value) {
    return
  }
  const [start, end] = props.range
  let currentValue = value || 0
  if (currentValue >= end) {
    currentValue = end - 1
  }

  if (currentValue < start) {
    currentValue = 0
  }
  const needScrollBlockNum = currentValue
  left.value = blockGroupByRange.value.groupSize * needScrollBlockNum - BallWidth.value / 2
  emit('change', currentValue)
}

const jieliuControlLocation = (e: MouseEvent) => {
  getCurrentLocation(e)
}

//  监听整个滑块
const listenSliderWithMousemove = () => {
  sliderRef.value?.addEventListener('mousemove', jieliuControlLocation)
}

// 鼠标点击回调
const clickBlock = (e: MouseEvent) => {
  getCurrentLocation(e)
  listenSliderWithMousemove()
}

const clearEvent = () => {
  sliderRef.value?.removeEventListener('mousemove', jieliuControlLocation)
}

watch(
  () => props.default,
  (value) => {
    scrollByCurrentRange(value)
  }
)
</script>

<style lang="scss" scoped>
@import './style.scss';
</style>
